package com.yanqu.road.server.gameplayer.module.minibind;

import com.yanqu.road.dao.impl.player.UserWechatBindDaoImpl;
import com.yanqu.road.entity.player.UserWechatBind;
import com.yanqu.road.logic.config.ChannelConfig;
import com.yanqu.road.logic.helper.CrossChannelHelper;
import com.yanqu.road.server.GameServer;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.base.GeneralModule;
import com.yanqu.road.server.helper.SignHelper;
import com.yanqu.road.server.manger.config.WechatBindMgr;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.string.StringUtils;

import java.net.URLEncoder;

public class WechatBindModule extends GeneralModule {
    public WechatBindModule(GamePlayer player) {
        super(player);
    }

    private UserWechatBind userData = null;

    @Override
    public boolean loadData() {
        userData = new UserWechatBindDaoImpl().getUserWechatBind(player.getUserId());
        return true;
    }

    @Override
    public boolean afterLoadData() {
        return true;
    }

    @Override
    public boolean saveData() {
        if (userData != null) {
            if (userData.isInsertOption()) {
                new UserWechatBindDaoImpl().add(userData);
            } else if (userData.isUpdateOption()) {
                new UserWechatBindDaoImpl().update(userData);
            }
        }
        return true;
    }

    @Override
    public void afterLogin() {
        initUserData();
    }

    public void initUserData() {
        String gameId = getGameId();
        if (StringUtils.isNullOrEmpty(gameId)) {
            return;
        }
        if (userData == null) {
            userData = new UserWechatBind(player.getUserId());
        }
    }

    public String getGameId() {
        return WechatBindMgr.getMiniGameId(player.getAppId());
    }

    public UserWechatBind getUserData() {
        return userData;
    }

    /**
     * 检查请求是否有效
     */
    public int checkReqValid() {
        if (userData == null) {
            return GameErrorCode.E_WX_BIND_NOT_GAME_ID;
        }
        int currentSecond = DateHelper.getCurrentSecond();
        long codeTime = userData.getLastGetBindTime();
        //判断一下是否24小时内超10次
        userData.getBindTimeList().removeIf(time -> currentSecond - time > DateHelper.DAY_SECONDS);
        if (currentSecond - codeTime > DateHelper.MINUTE_SECONDS * ChannelConfig.WX_BIND_CODE_VALID_MINUTE) {
            if (userData.getBindTimeList().size() >= ChannelConfig.WX_BIND_CODE_VALID_NUM_IN_24HOUR) {
                return GameErrorCode.E_WX_BIND_OUT_24HOUR_TIMES;
            }
        }
        return 0;
    }

    /**
     * 计算加密前绑定码
     *
     * @return
     */
    public String getBindCode() throws Exception {
        //绑角码： 加密前参数格式： 平台 uid|服 id|角色 id|角色名|游戏 id|当前时间戳
        //当次绑定码5分钟内有效，24小时内只允许生成10次绑定码
        int currentSecond = DateHelper.getCurrentSecond();
        long codeTime = userData.getLastGetBindTime();

        // 5分钟内只能请求一次
        if (currentSecond - codeTime > DateHelper.MINUTE_SECONDS * ChannelConfig.WX_BIND_CODE_VALID_MINUTE) {
            codeTime = currentSecond;
        } else {
            return userData.getBindCode();
        }

        if (codeTime == 0) {
            codeTime = currentSecond;
        }

        StringBuilder codeBuilder = new StringBuilder();
        codeBuilder.append(player.getUserInfo().getPlatformUserId()).append("|");
        codeBuilder.append(GameServer.getInstance().getServerId()).append("|");
        codeBuilder.append(player.getUserId()).append("|");
        String encodeNickName = URLEncoder.encode(player.getUserInfo().getNickName(), "UTF-8");
        codeBuilder.append(encodeNickName).append("|");
        codeBuilder.append(getGameId()).append("|");
        codeBuilder.append(codeTime);

        String code = codeBuilder.toString();

        String encryptCode = SignHelper.encryptByAES(code, ChannelConfig.WX_BIND_CODE_SECRET);

        userData.setBindCode(encryptCode);
        userData.setLastGetBindTime(codeTime);
        userData.addBindTimeList(codeTime);

        return encryptCode;
    }
}
